var path = require("path");
var fs = require("fs");

// 创建express应用实例
var express = require("express");
var app = express();

// 创建服务器实例
var server = require("http").Server(app);

// 引入ws
var WebSocket = require("ws");

// websocket服务端监socket监听在一个独立于express存在的8080端口 等待客户端连接
var wss = new WebSocket.Server({ port: 8080 });

const host = "http://localhost";
const port = 3000;
const baseUrl = `${host}:${port}`;

// 准备客户端存储对象 cid-ws 结构
const clients = {};

/* 
有客户端请求接入 入参ws即为接入的客户端socket对象 
连接事件处理函数中的ws即客户端套接字对象
*/
wss.on("connection", function connection(ws) {
  console.log("server: receive connection from client");

  // 此处使用时间戳的最后3位作为当前客户端的id
  const cid = (Date.now() + "").slice(-3);

  // 将该客户端存下来 时间戳:socket
  clients[cid] = ws;
  ws.cid = cid;
  console.log("clients", Object.keys(clients));

  // 接收到该客户端发来的消息 message即客户端发来的消息
  ws.on("message", function incoming(message) {
    // 文件上传
    try {
      const data = JSON.parse(message);
      console.log("data=", data);

      const metaData = data.metadata;
      const fileName = metaData.fileName;
      const fileSize = metaData.fileSize;
      const to = metaData.to;
      const from = metaData.from;

      // 将json版字符串数组转为字节数组（文件原始数据）
      const fileData = new Uint8Array(data.fileData);

      // 保存文件
      fs.writeFileSync(
        // 保存到 工程根目录/public/文件名
        path.resolve("public", fileName),

        // 文件的字节数据
        fileData
      );

      // 通知接受者来下载
      clients[to].send(
        `
        ${ws.cid} 向您发送了一个文件 
        <br/>
        ${JSON.stringify(metaData)}
        <br/>
        <a target="_blank" href="${baseUrl}/${fileName}">下载文件</a>
        `
      );

      // 发送文件数据给客户端1.0
      // clients[to].send(fileData);

      // 发送数据给客户端2.0
      // const jsonBody = JSON.stringify({
      //   metaData,
      //   fileData: Array.from(fileData),
      // });
      // clients[to].send(jsonBody);

      clients[ws.cid].send(`文件发送成功！`);
    } catch (err) {
      console.log("catch", err);

      // 普通消息
      console.log("message", message);
      // ws.send("server#" + message);

      // 转发给它想要发送的其它客户端
      const [to, msg] = message.toString().split("#");
      // ws.send(`${message} got form ya ${ws.cid}`)
      // console.log("to=", to);
      // console.log("clients=", clients);

      clients[to].send(`${ws.cid}:${msg}`);
    }
  });

  // 该客户端主动断开连接
  ws.on("close", function (code, reason) {
    console.log("客户端已断开连接");
  });

  // 与该客户端的连接发送错误
  ws.on("error", function (err) {
    //处理错误
    console.log("ws on error", err);
  });

  // 立刻给刚刚接入的客户端发送消息
  // 立刻告知客户端的cid
  ws.send(`server: your cid is ${cid}`);
});

// 静态资源目录设置
app.use(express.static(__dirname + "/public"));

// 集成json请求体解析中间件
app.use(express.json());

// 允许跨域
const cors = require('cors');
app.use(cors());

/* 在http的3000端口返回页面给客户端 */
app.get("/", function (req, res) {
  res.sendfile(path.resolve("../web/index.html"));
});

/* 注册推送接口 */
app.post("/push", (req, res, next) => {
  const jsonData = req.body; // 获取请求体中的 JSON 数据
  const { ids, msg, type } = jsonData;

  // 在这里处理 jsonData
  ids.forEach((id) => {
    // 从obj中按照cid查找到目标客户端 并向其发送消息
    clients[id] && clients[id].send(msg);
  });

  // 向发起推送请求的客户端返回响应
  res.send(`数据已接收并处理${JSON.stringify(jsonData)}`);
});

// 将应用实例挂载到3000端口
app.listen(port);
